﻿using System;
using System.Web;
using System.IO;
using Newtonsoft.Json;
using System.Text;
using log4net;

namespace GrainManage.Server
{
    public enum LogLevel { Fatal, Error, Warn, Info, Debug }

    public class LogUtil
    {

        public static void SetConfig(string configFilePath)
        {
            if (configFilePath.StartsWith("~") || !configFilePath.Contains(":"))
            {
                configFilePath = HttpContext.Current.Server.MapPath(configFilePath);
            }
            log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(configFilePath));
        }

        public static void Write(string message, Exception e, LogLevel level)
        {
            var _Logger = GetLog();
            switch (level)
            {
                case LogLevel.Fatal:

                    if (_Logger.IsFatalEnabled)
                    {
                        _Logger.Fatal(message, e);
                    }
                    break;
                case LogLevel.Error:
                    if (_Logger.IsErrorEnabled)
                    {
                        _Logger.Error(message, e);
                    }
                    break;
                case LogLevel.Warn:
                    if (_Logger.IsWarnEnabled)
                    {
                        _Logger.Warn(message, e);
                    }
                    break;
                case LogLevel.Info:
                    if (_Logger.IsInfoEnabled)
                    {
                        _Logger.Info(message, e);
                    }
                    break;
                case LogLevel.Debug:
                    if (_Logger.IsDebugEnabled)
                    {
                        _Logger.Debug(message, e);
                    }
                    break;
            }
        }

        public static void Write(string message, LogLevel level)
        {
            var _Logger = GetLog();
            switch (level)
            {
                case LogLevel.Fatal:
                    if (_Logger.IsFatalEnabled)
                    {
                        _Logger.Fatal(message);
                    }
                    break;
                case LogLevel.Error:
                    if (_Logger.IsErrorEnabled)
                    {
                        _Logger.Error(message);
                    }
                    break;
                case LogLevel.Warn:
                    if (_Logger.IsWarnEnabled)
                    {
                        _Logger.Warn(message);
                    }
                    break;
                case LogLevel.Info:
                    if (_Logger.IsInfoEnabled)
                    {
                        _Logger.Info(message);
                    }
                    break;
                case LogLevel.Debug:
                    if (_Logger.IsDebugEnabled)
                    {
                        _Logger.Debug(message);
                    }
                    break;
            }
        }

        public static string GetMessage<InputParameter, OutputParameter>(System.Reflection.MethodBase method, Exception e, InputParameter input, OutputParameter output, string requestWay)
        {
            var methodName = method.DeclaringType.FullName + "." + method.Name;
            StringBuilder builder = new StringBuilder();
            builder.AppendLine("Client IP: " + GrainManage.Server.Tool.IPUtil.RequestHostAddress);

            if (!string.IsNullOrEmpty(requestWay))
            {
                builder.AppendLine("Request Way: " + requestWay);
            }
            if (!string.IsNullOrEmpty(methodName))
            {
                builder.AppendLine("Method: " + methodName);
            }
            if (input != null)
            {
                builder.AppendLine("Input Parameter:");
                if (typeof(InputParameter) == typeof(string))
                {
                    builder.AppendLine(input as string);
                }
                else
                {
                    builder.AppendLine(Serialize(input));
                }
            }
            if (output != null)
            {
                builder.AppendLine("Output Parameter:");

                if (typeof(OutputParameter) == typeof(string))
                {
                    builder.AppendLine(input as string);
                }
                else
                {
                    builder.AppendLine(Serialize(output));
                }
            }
            if (e != null)
            {

                if (!string.IsNullOrEmpty(e.Message))
                {
                    builder.AppendLine("Message: " + e.Message);
                }
                if (!string.IsNullOrEmpty(e.Source))
                {
                    builder.AppendLine("Source: " + e.Source);
                }
                if (e.TargetSite != null)
                {
                    builder.AppendLine("TargetSite: " + e.TargetSite.DeclaringType.FullName + "." + e.TargetSite.Name);
                }
                if (!string.IsNullOrEmpty(e.StackTrace))
                {
                    builder.AppendLine("StackTrace:");
                    builder.AppendLine(e.StackTrace);
                }
                if (e.InnerException != null && string.IsNullOrEmpty(e.InnerException.Message))
                {
                    builder.AppendLine("InnerException Message: " + e.InnerException.Message);
                }
            }
            builder.AppendLine();
            return builder.ToString();
        }

        public static bool CanWrite(LogLevel level)
        {
            var _Logger = GetLog();
            switch (level)
            {
                case LogLevel.Fatal:
                    return _Logger.IsFatalEnabled;
                case LogLevel.Error:
                    return _Logger.IsErrorEnabled;
                case LogLevel.Warn:
                    return _Logger.IsWarnEnabled;
                case LogLevel.Info:
                    return _Logger.IsInfoEnabled;
                case LogLevel.Debug:
                    return _Logger.IsDebugEnabled;
                default:
                    return false;
            }
        }

        #region 辅助方法

        private static ILog GetLog<T>()
        {
            ILog logger = log4net.LogManager.GetLogger(typeof(T));
            return logger;
        }

        private static ILog GetLog()
        {
            ILog logger = log4net.LogManager.GetLogger("AllLog");
            return logger;
        }

        private static string Serialize(object model)
        {
            var result = string.Empty;
            if (model != null)
            {
                if (!(model is string) && !(model is ValueType))
                {
                    result = JsonConvert.SerializeObject(model, Formatting.Indented);
                }
                else
                {
                    result = Convert.ToString(model);
                }
            }
            return result;
        }

        #endregion

    }
}